﻿using System.Collections.Generic;
using System.Linq;
using NHibernate.Criterion;
using TestBat.IModels.Domain;
using TestBat.IModels.Models;
using TestBat.IModels.Repositories;
using TestBat.Models.Attributes;

namespace TestBat.Models.Models
{
    public class TraineeModel : Model, ITraineeModel
    {
        public TraineeModel(ITraineeRepository traineeRepository)
        {
            this.traineeRepository = traineeRepository;
        }

        [Conversation(ConversationEndMode.CommitAndContinue)]
        public void Save(ITrainee trainee)
        {
            Validate(trainee);

            traineeRepository.MakePersistent(trainee);
        }

        [Conversation(ConversationEndMode.CommitAndContinue)]
        public void Delete(ITrainee trainee)
        {
            traineeRepository.MakeTransient(trainee);
        }

        [Conversation(ConversationEndMode.CommitAndContinue)]
        public void Revert(ITrainee trainee)
        {
            traineeRepository.Refresh(trainee);
        }

        [Conversation]
        public void AddTraineeGroup(ITrainee trainee, ITraineeGroup traineeGroup)
        {
            trainee.TraineeGroups.Add(traineeGroup);
            traineeGroup.Trainees.Add(trainee);

            traineeRepository.MakePersistent(trainee);
        }

        [Conversation]
        public void RemoveTraineeGroup(ITrainee trainee, ITraineeGroup traineeGroup)
        {
            trainee.TraineeGroups.Remove(traineeGroup);
            traineeGroup.Trainees.Remove(trainee);

            traineeRepository.MakePersistent(trainee);
        }

        [Conversation]
        public IList<ITrainee> GetAll()
        {
            return traineeRepository.GetAllOrderedBy("Username", true);
        }

        [Conversation]
        public bool CheckTraineeCredentials(string username, string password)
        {
            DetachedCriteria c = DetachedCriteria.For<ITrainee>()
                .Add(Expression.Eq("Username", username)).Add(Expression.Eq("Password", password));
            IList<ITrainee> list = traineeRepository.GetByCriteria<ITrainee>(c);

            // HACK: remove all invalid trainees (again) because NHibernate's query might be case insensitive (depending on the DB collation)
            List<ITrainee> list2 = list.ToList<ITrainee>();
            list2.RemoveAll(element => string.Compare(element.Password, password, false) != 0 || string.Compare(element.Username, username, false) != 0);
            
            return list2.Count != 0;
        }

        [Conversation]
        public ITrainee GetByUsername(string username)
        {
            DetachedCriteria c = DetachedCriteria.For<ITrainee>()
                .Add(Expression.Eq("Username", username));

            return traineeRepository.GetByCriteria<ITrainee>(c).FirstOrDefault<ITrainee>();
        }

        private readonly ITraineeRepository traineeRepository;
    }
}
